library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity framebuilder IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       clk                : IN    std_logic;
       
       grant_valid        : IN    std_logic;
       fifo_halffull      : in    std_logic;
       in_to_send         : in    std_logic_vector(7 DOWNTO 0); 
       write_enable       : in    std_logic_vector(num_requester-1 DOWNTO 0);
       
       read_enable        : out   std_logic;
       start_schedule     : out   std_logic; 
       out_to_send        : out   std_logic_vector(7 DOWNTO 0);
       data_to_fifo_we    : out   std_logic     
    );
end framebuilder;


architecture Behavioral of framebuilder is
   
   signal payload_amount_buffer : unsigned(5 downto 0) := (others => '0');
   signal seq_nr_counter : unsigned(7 downto 0) := (others => '0');
   
   TYPE STATE_TYPE IS (
      idle,
      preamble,
      seq_nr,
      module_id,
      payload_amount,
      crc,
      payload
   );
 
   SIGNAL state : STATE_TYPE := idle;
   
   
      
begin
    
     

process (clk)
begin
  if rising_edge(clk) then
    
    case state is
      
      when idle =>
        if grant_valid='1' and fifo_halffull='0' then
          payload_amount_buffer <= unsigned(in_to_send(5 downto 0));
          state <= preamble;
        end if;
        
      when preamble =>
          state <= seq_nr; 
       
      when seq_nr =>
          state <= module_id; 
          seq_nr_counter <= seq_nr_counter +1;
       
      when module_id =>
          state <= payload_amount;   
       
      when payload_amount =>
          state <= crc;   
          
      when crc =>
          state <= payload;
          
      when payload =>
          if unsigned(write_enable)>0 then
            payload_amount_buffer <= payload_amount_buffer-1;
          end if;
          if payload_amount_buffer=1 then
            state <= idle;  
          end if;
        
        
    
    end case;
    
  end if;
end process;

  with state select out_to_send <=
    "11111110" when preamble,
    std_logic_vector(seq_nr_counter) when seq_nr,
    (7 downto num_requester => '0') & write_enable when module_id,
    "00" & std_logic_vector(payload_amount_buffer) when payload_amount,
    "00111100" when crc,
    in_to_send when payload,
    "11000011" when others;

  read_enable <= '1' when state=payload else '0';
  
  start_schedule <= '1' when state=preamble else '0';
  data_to_fifo_we <= '0' when (state=idle or (state=payload and unsigned(write_enable)=0)) else '1';

end Behavioral;






